package com.gopay.bis.service.bank.impl;

import com.gopay.bis.common.util.BisPayCheckUtils;
import com.gopay.bis.common.util.SendSmsUtils;
import com.gopay.bis.manager.bank.BankOrderManager;
import com.gopay.bis.manager.bank.external.BisPayMessageManager;
import com.gopay.bis.manager.bank.payconfig.BisBankExtConfigManager;
import com.gopay.bis.service.bank.BankIntrChannConfService;
import com.gopay.bis.service.bank.BankOrderService;
import com.gopay.bis.service.bank.BisExpayDtlService;
import com.gopay.bis.service.bank.external.BisExternalPlatformService;
import com.gopay.bis.service.bank.go.GoBankService;
import com.gopay.bis.service.bank.query.BisBankWhiteListMerchantsService;
import com.gopay.bis.service.bank.sms.SmsSupportController;
import com.gopay.common.Result;
import com.gopay.common.cipher.utils.LoggerMaskUtils;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BankOrderStatus;
import com.gopay.common.constants.bank.BankOrderType;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.constants.bank.QueryNeedCertConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.constants.sms.SmsAdviceEnum;
import com.gopay.common.constants.trans.GatewaySource;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.cps.dao.order.CpsGeneralReceiptOrderQueryDAO;
import com.gopay.common.cps.manager.order.CpsGeneralMainOrderQueryManager;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.ExPayBaseMessage;
import com.gopay.common.domain.bank.external.BisBankMerchant;
import com.gopay.common.domain.bank.external.BisPayMessage;
import com.gopay.common.domain.bank.yeepay.expay.YeePayExPayMessage;
import com.gopay.common.domain.bank.yspay.expay.pay.YspayAdPayMessage;
import com.gopay.common.domain.bis.BaseBisBankExtConfig;
import com.gopay.common.domain.bis.RouteMessage;
import com.gopay.common.domain.cps.CpsGenMainOrder;
import com.gopay.common.domain.cps.CpsGenReceiptOrder;
import com.gopay.common.exception.GopayException;
import com.gopay.common.order.bankorder.trade.InitialSpringBeanName;
import com.gopay.common.order.bankorder.trade.TradeType;
import com.gopay.common.util.CertNoVerifyUtil;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.HttpTransport;
import com.gopay.common.util.RSAEncoderUtil;
import com.gopay.common.util.spring.SpringContextUtil;
import com.gopay.remote.bank.ExPayInteractRemoteService;
import com.gopay.remote.bank.autoroute.BankRoute;
import com.gopay.remote.cashier.bis.CashierBgNotifyRemoteService;
import com.gopay.remote.cps.bis.ErrOrderRecordRemoteService;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.hibernate.StaleObjectStateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

/**
 * 快捷支付操作Service实现
 * 
 * @BankExPayInteractServiceImpl.java
 * @author zhengxue @2015-05-05 上午9:45:01 www.gopay.com.cn Inc.All rights
 *         reserved.
 */
@Service("exPaybankInteractService")
public class BankExPayInteractServiceImpl implements ExPayInteractRemoteService {

    private static Logger logger = LoggerFactory.getLogger(BankExPayInteractServiceImpl.class);
    private static final String AUTO_ROUTING = "on"; // 银行自动路由开关
    private static final String OLD_GOPAY = "OLDGOPAY"; // 国付宝钱包老版本标示

    @Resource(name = "bankOrderService")
    private BankOrderService bankOrderService;

    @Resource(name = "bisExpayDtlService")
    private BisExpayDtlService bisExpayDtlService;

    @Resource(name = "bisExternalPlatformService")
    private BisExternalPlatformService bisExternalPlatformService;

    @Resource(name = "cpsGeneralMainOrderQueryManager")
    private CpsGeneralMainOrderQueryManager mainOrderQuery;

    @Resource(name = "bankOrderManager")
    private BankOrderManager bankOrderManager;

    @Resource(name = "bisBankExtConfigManager")
    BisBankExtConfigManager bisBankExtConfigManager;

    @Resource(name = "bisPayMessageManager")
    BisPayMessageManager bisPayMessageManager;

    @Resource(name = "bankIntrChannConfService")
    private BankIntrChannConfService bankIntrChannConfService;

    @Resource(name = "bisConfig")
    private Map<String, String> bisConfig;

    @Resource(name = "bankRouteService")
    private BankRoute bankRouteService;

    @Resource(name = "normalBankRouteService")
    private BankRoute normalBankRouteService;

    @Resource(name = "goBankService")
    private GoBankService goBankService;

    @Resource(name = "notifyCashier")
    private HttpTransport notifyCashier;

    @Resource(name = "cashierBgNotifyRemoteService")
    private CashierBgNotifyRemoteService cashierBgNotifyRemoteService;

    @Resource(name = "smsConfig")
    private Map<String, String> smsConfig;

    // 短信验证码处理类
    public SmsSupportController smsController;

    @Resource(name = "errOrderRecordService")
    protected ErrOrderRecordRemoteService errOrderRecordService;

    @Resource(name = "bisBankWhiteListMerchantsService")
    private BisBankWhiteListMerchantsService bisBankWhiteListMerchantsService;
    
    @Resource(name = "cpsGeneralReceiptOrderQueryDAO")
    private CpsGeneralReceiptOrderQueryDAO cpsGeneralReceiptOrderQueryDAO;

    /**
     * 是否需要cvv2
     */
    @Override
    public Result queryCvn(ExPayBaseMessage base) {
    	/**央行检测 要求身份照掩码处理 sj 2017-11-03*/
        logger.error("BankExPayInteractServiceImpl快捷支付queryCvn处理base对象：" + LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
        Result result = new Result();
        try {
            // 银行业务产品码
            String bankBusProd = base.getBankBusProd().value;
            BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
            // 获取主订单表信息
            BaseMessage message = goBankService.buildSign(base.getOrderId(), "");
            if (isRouteOrWhiteList(message.getSpecial2())) {
                // 增加银行自动路由开关 add by zhengxue
                base.setSpecial("queryCvn"); // 自动路由记录日志remark
                RouteMessage routeMessage = getRouteReq(message, base);

                if (IntTxnCd._00500.value.equals(message.getSpecial4())
                        || BankConstants.GOPAY_CHONGZHI_CUSTID.equals(message.getSpecial2())) {
                    // 充值交易走通用方案
                    bankConfig = normalBankRouteService.getNormalRoute(routeMessage);
                    if (BankConstants.GOPAY_CHONGZHI_CUSTID.equals(message.getSpecial2())
                            && !IntTxnCd._00500.value.equals(message.getSpecial4())) {
                        // 非充值订单获取merId为GFB0000001
                        logger.error(message.getOrderId() + " BankExPayInteractServiceImpl queryCvn获取商户ID为: "
                                + message.getSpecial2());
                    }
                } else {
                    bankConfig = bankRouteService.getRoute(routeMessage);
                }
                bankOrderService.addBankRouteLog(routeMessage); // 记录银行自动路由日志
            } else {
                // 获取银行接口通道配置信息
                bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(),
                        base.getBank());
            }

            if (BisBankInterfaceChannel._14.value.equals(bankConfig.getChCode())) {
                // 银行产品空通道
                logger.error(base.getOrderId() + " BankExPayInteractServiceImpl queryCvn获取银行产品空通道 ");
                result.setResultCode(ProcCodeConstants.PROC_CODE_100E6090);
                result.setSuccess(false);
                return result;
            }

            base.setBankIntrChann(BisBankInterfaceChannel.get(bankConfig.getChCode()));
            // 平台外部清算机构代码
            String outStlmCd = InitialSpringBeanName.getOutStlmCd(bankConfig.getChCode(), bankBusProd, base.getBank());
            base.setOutStlmCd(outStlmCd);
            // 获取SPRING加载的快捷BeanName
            String beanName = outStlmCd + "-" + "EXPAY";
            ExPayInteractRemoteService exPayService = (ExPayInteractRemoteService) SpringContextUtil.getBean(beanName);

            // 设置一级私钥路径
            base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
            // 设置一级私钥密码
            base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
            // 设置二级私钥路径
            base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
            // 设置二级私钥密码
            base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
            // 设置公钥路径
            base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
            // 设置商户号
            base.setMerID(bankConfig.getIntrMernum1());
            // 设置二级商户号
            base.setMerID2nd(bankConfig.getIntrMernum2());
            // 设置结算账户网点联行号
            base.setBranchCode(bankConfig.getBranchCode());
            // 设置银行支付地址
            base.setPayUrl(bankConfig.getPayUrl());
            // 设置支付后台通知地址
            base.setPayRuturnUrl(bankConfig.getPayRuturnUrl());
            // 设置支付后前通知地址
            base.setPayNotifyUrl(bankConfig.getPayNotifyUrl());

            // 发送请求
            result = exPayService.queryCvn(base);
            logger.error("BankExPayInteractServiceImpl是否需要cvv2请求返回处理对象：" + ToStringBuilder.reflectionToString(result));
        } catch (Exception e) {
            logger.error("BankExPayInteractServiceImpl queryCvn error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }

    /**
     * 认证接口
     */
    @Override
    public Result certification(ExPayBaseMessage base) {
        // 日志输出隐藏信用卡cvv2
        ExPayBaseMessage logData = getPrintMsg(base);
        /**央行检测 要求身份照掩码处理 sj 2017-11-03*/
        logger.error(
                "BankExPayInteractServiceImpl快捷支付certification处理base对象：" + LoggerMaskUtils.maskString(ReflectionToStringBuilder.toStringExclude(logData,"availableDate","cvv2")));
        Result result = new Result();
        try {
            // 检查该订单是否允许进行鉴权
            smsController.checkCertification(base);

            if ("TBANK".equals(base.getBank())) {
                // 根据环境返回TBANK结果，生产返回失败其他环境返回成功
                if ("on".equals(bisConfig.get("BIS.TBANK.FLAG"))) {
                    // TBANK返回成功
                    result.setSuccess(true);
                    result.setModel("flag", true);
                    bisExpayDtlService.addExpayDtl(base);
                } else {
                    // TBANK返回失败
                    result.setSuccess(true);
                    result.setModel("flag", false);
                }
                return result;
            }

            checkRequest(base);

            // 银行业务产品码
            String bankBusProd = base.getBankBusProd().value;
            BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
            // boolean isbankRoute = false; // 是否自动路由标识
            // BaseMessage message = new BaseMessage();
            // if (!"3".equals(base.getSpecialChCode())) {
            // // 基金交易跳过自动路由
            // // 获取主订单表信息
            // message = goBankService.buildSign(base.getOrderId(), "");
            // isbankRoute = isRouteOrWhiteList(message.getSpecial2());
            // }

            BaseMessage message = goBankService.buildSign(base.getOrderId(), "");
            if (isRouteOrWhiteList(message.getSpecial2())) {
                // 增加银行自动路由开关 add by zhengxue
                base.setSpecial("certification"); // 自动路由记录日志remark
                RouteMessage routeMessage = getRouteReq(message, base);

                if (IntTxnCd._00500.value.equals(message.getSpecial4())
                        || BankConstants.GOPAY_CHONGZHI_CUSTID.equals(message.getSpecial2())) {
                    // 充值交易走通用方案
                    bankConfig = normalBankRouteService.getNormalRoute(routeMessage);
                    if (BankConstants.GOPAY_CHONGZHI_CUSTID.equals(message.getSpecial2())
                            && !IntTxnCd._00500.value.equals(message.getSpecial4())) {
                        // 非充值订单获取merId为GFB0000001
                        logger.error(message.getOrderId() + " BankExPayInteractServiceImpl certification获取商户ID为: "
                                + message.getSpecial2());
                    }
                } else {
                    bankConfig = bankRouteService.getRoute(routeMessage);
                }
                bankOrderService.addBankRouteLog(routeMessage); // 记录银行自动路由日志
            } else {
                // 获取银行接口通道配置信息
                bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(),
                        base.getBank());
                if ("1".equals(base.getSpecialChCode())) {
                    // 钱包三冲交易固定走易宝通道
                    if (!BisBankInterfaceChannel._09.toString().equals(bankConfig.getChCode())) {
                        // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
                        bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(
                                base.getBankBusProd(), BisBankInterfaceChannel._09, base.getBank());
                        logger.error("BankExPayInteractServiceImpl快捷支付certification specialChCode: 1");
                    }
                }
                if ("2".equals(base.getSpecialChCode())) {
                    // 钱包天宜盈交易固定走民生代扣通道
                    if (!BisBankInterfaceChannel._11.toString().equals(bankConfig.getChCode())) {
                        // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
                        bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(
                                base.getBankBusProd(), BisBankInterfaceChannel._11, base.getBank());
                        logger.error("BankExPayInteractServiceImpl快捷支付certification specialChCode: 2");
                    }
                }
            }

            if (BisBankInterfaceChannel._14.value.equals(bankConfig.getChCode())) {
                // 银行产品空通道
                logger.error(base.getOrderId() + " BankExPayInteractServiceImpl certification获取银行产品空通道 ");
                result.setResultCode(ProcCodeConstants.PROC_CODE_100E6090);
                result.setSuccess(false);
                return result;
            }

            // 校验银行业务产品是否支持该通道
            checkBankBussProdAndIntrChan(bankConfig, bankBusProd);
            base.setBankIntrChann(BisBankInterfaceChannel.get(bankConfig.getChCode()));
            // 平台外部清算机构代码
            String outStlmCd = InitialSpringBeanName.getOutStlmCd(bankConfig.getChCode(), bankBusProd, base.getBank());
            base.setOutStlmCd(outStlmCd);
            // 获取SPRING加载的快捷BeanName
            String beanName = outStlmCd + "-" + "EXPAY";
            ExPayInteractRemoteService exPayService = (ExPayInteractRemoteService) SpringContextUtil.getBean(beanName);

            // 设置一级私钥路径
            base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
            // 设置一级私钥密码
            base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
            // 设置二级私钥路径
            base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
            // 设置二级私钥密码
            base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
            // 设置公钥路径
            base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
            // 设置商户号
            base.setMerID(bankConfig.getIntrMernum1());
            // 设置二级商户号
            base.setMerID2nd(bankConfig.getIntrMernum2());
            // 设置结算账户网点联行号
            base.setBranchCode(bankConfig.getBranchCode());
            // 设置银行支付地址
            base.setPayUrl(bankConfig.getPayUrl());
            // 设置支付后台通知地址
            base.setPayRuturnUrl(bankConfig.getPayRuturnUrl());
            // 设置支付后前通知地址
            base.setPayNotifyUrl(bankConfig.getPayNotifyUrl());

            // 认证请求
            result = exPayService.certification(base);
            // 鉴权通过新增一条快捷流水表
            if (result.isSuccess() && (boolean) result.getModel("flag")) {
                bisExpayDtlService.addExpayDtl(base);
            }
            logger.error("BankExPayInteractServiceImpl认证请求返回处理对象：" + ToStringBuilder.reflectionToString(result));
        } catch (GopayException e) {
            logger.error("BankExPayInteractServiceImpl certification error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankExPayInteractServiceImpl certification error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }

    /**
     * 发送短信验证码接口
     */
    @Override
    public Result sendSms(ExPayBaseMessage base) {
        // 日志输出隐藏信用卡cvv2
        ExPayBaseMessage logData = getPrintMsg(base);
        /**央行检测 要求身份照掩码处理 sj 2017-11-03*/
        logger.error("BankExPayInteractServiceImpl快捷支付sendSms处理base对象：" + LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(logData)));
        Result result = new Result();
        try {
            // 发短信时对比要素是否和鉴权成功的要素匹配，不匹配抛异常
            bisExpayDtlService.checkSendSmsCerElements(base);
            // 银行业务产品码
            String bankBusProd = base.getBankBusProd().value;
            BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
            // boolean isbankRoute = false; // 是否自动路由标识
            // BaseMessage message = new BaseMessage();
            // if (!"3".equals(base.getSpecialChCode())) {
            // // 基金交易跳过自动路由
            // // 获取主订单表信息
            // message = goBankService.buildSign(base.getOrderId(), "");
            // isbankRoute = isRouteOrWhiteList(message.getSpecial2());
            // }

            BaseMessage message = goBankService.buildSign(base.getOrderId(), "");
            if (isRouteOrWhiteList(message.getSpecial2())) {
                // 增加银行自动路由开关 add by zhengxue
                base.setSpecial("sendSms"); // 自动路由记录日志remark
                RouteMessage routeMessage = getRouteReq(message, base);

                if (IntTxnCd._00500.value.equals(message.getSpecial4())
                        || BankConstants.GOPAY_CHONGZHI_CUSTID.equals(message.getSpecial2())) {
                    // 充值交易走通用方案
                    bankConfig = normalBankRouteService.getNormalRoute(routeMessage);
                    if (BankConstants.GOPAY_CHONGZHI_CUSTID.equals(message.getSpecial2())
                            && !IntTxnCd._00500.value.equals(message.getSpecial4())) {
                        // 非充值订单获取merId为GFB0000001
                        logger.error(message.getOrderId() + " BankExPayInteractServiceImpl sendSms获取商户ID为: "
                                + message.getSpecial2());
                    }
                } else {
                    bankConfig = bankRouteService.getRoute(routeMessage);
                }
                bankOrderService.addBankRouteLog(routeMessage); // 记录银行自动路由日志
            } else {
                // 获取银行接口通道配置信息
                bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(),
                        base.getBank());
                if ("1".equals(base.getSpecialChCode())) {
                    // 钱包交易固定走易宝通道
                    if (!BisBankInterfaceChannel._09.toString().equals(bankConfig.getChCode())) {
                        // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
                        bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(
                                base.getBankBusProd(), BisBankInterfaceChannel._09, base.getBank());
                        logger.error("BankExPayInteractServiceImpl快捷支付sendSms specialChCode: 1");
                    }
                }
                if ("2".equals(base.getSpecialChCode())) {
                    // 钱包天宜盈交易固定走民生代扣通道
                    if (!BisBankInterfaceChannel._11.toString().equals(bankConfig.getChCode())) {
                        // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
                        bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(
                                base.getBankBusProd(), BisBankInterfaceChannel._11, base.getBank());
                        logger.error("BankExPayInteractServiceImpl快捷支付certification specialChCode: 2");
                    }
                }
            }

            if (BisBankInterfaceChannel._14.value.equals(bankConfig.getChCode())) {
                // 银行产品空通道
                logger.error(base.getOrderId() + " BankExPayInteractServiceImpl sendSms获取银行产品空通道 ");
                result.setResultCode(ProcCodeConstants.PROC_CODE_100E6090);
                result.setSuccess(false);
                return result;
            }

            base.setBankIntrChann(BisBankInterfaceChannel.get(bankConfig.getChCode()));
            // 平台外部清算机构代码
            String outStlmCd = InitialSpringBeanName.getOutStlmCd(bankConfig.getChCode(), bankBusProd, base.getBank());
            base.setOutStlmCd(outStlmCd);
            // 获取SPRING加载的快捷BeanName
            String beanName = outStlmCd + "-" + "EXPAY";
            ExPayInteractRemoteService exPayService = (ExPayInteractRemoteService) SpringContextUtil.getBean(beanName);

            if (!BisPayCheckUtils.checkExternalOrderID(base.getOrderId())) {
                // 设置一级私钥路径
                base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
                // 设置一级私钥密码
                base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
                // 设置二级私钥路径
                base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
                // 设置二级私钥密码
                base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
                // 设置公钥路径
                base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
                // 设置商户号
                base.setMerID(bankConfig.getIntrMernum1());
                // 设置二级商户号
                base.setMerID2nd(bankConfig.getIntrMernum2());
                // 设置结算账户网点联行号
                base.setBranchCode(bankConfig.getBranchCode());
                // 设置银行支付地址
                base.setPayUrl(bankConfig.getPayUrl());
                // 设置支付后台通知地址
                base.setPayRuturnUrl(bankConfig.getPayRuturnUrl());
                // 设置支付后前通知地址
                base.setPayNotifyUrl(bankConfig.getPayNotifyUrl());
            }

            // 发送短信验证码请求
            result = exPayService.sendSms(base);
            // 短信发送成功后更新快捷流水表
            if (result.isSuccess() && (boolean) result.getModel("flag")) {
                bisExpayDtlService.updateSmsApplyDtl(base);
            }
            logger.error("BankExPayInteractServiceImpl发送短信请求返回处理对象：" + ToStringBuilder.reflectionToString(result));
        } catch (GopayException ex) {
            logger.error("BankExPayInteractServiceImpl sendSms error: ", ex);
            result.setResultCode(ex.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankExPayInteractServiceImpl sendSms error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }

    /**
     * 验证短信验证码接口
     */
    @Override
    public Result checkSms(ExPayBaseMessage base) {
        // 日志输出隐藏信用卡cvv2
        ExPayBaseMessage logData = getPrintMsg(base);
        /**央行检测 要求身份照掩码处理 sj 2017-11-03*/
        logger.error("BankExPayInteractServiceImpl快捷支付checkSms处理base对象：" + LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(logData)));
        Result result = new Result();
        try {
            
             //校验时对比要素是否和鉴权成功的要素匹配，是否经过短信申请，不匹配抛异常
             bisExpayDtlService.checkSmsCerElements(base);
            // 银行业务产品码
            String bankBusProd = base.getBankBusProd().value;
            BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
            BaseMessage message = goBankService.buildSign(base.getOrderId(), "");
            if (isRouteOrWhiteList(message.getSpecial2())) {
                // 增加银行自动路由开关 add by zhengxue
                base.setSpecial("checkSms"); // 自动路由记录日志remark
                RouteMessage routeMessage = getRouteReq(message, base);

                if (IntTxnCd._00500.value.equals(message.getSpecial4())
                        || BankConstants.GOPAY_CHONGZHI_CUSTID.equals(message.getSpecial2())) {
                    // 充值交易走通用方案
                    bankConfig = normalBankRouteService.getNormalRoute(routeMessage);
                    if (BankConstants.GOPAY_CHONGZHI_CUSTID.equals(message.getSpecial2())
                            && !IntTxnCd._00500.value.equals(message.getSpecial4())) {
                        // 非充值订单获取merId为GFB0000001
                        logger.error(message.getOrderId() + " BankExPayInteractServiceImpl checkSms获取商户ID为: "
                                + message.getSpecial2());
                    }
                } else {
                    bankConfig = bankRouteService.getRoute(routeMessage);
                }
                bankOrderService.addBankRouteLog(routeMessage); // 记录银行自动路由日志
            } else {
                // 获取银行接口通道配置信息
                bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(),
                        base.getBank());
                if ("1".equals(base.getSpecialChCode())) {
                    // 钱包交易固定走易宝通道
                    if (!BisBankInterfaceChannel._09.toString().equals(bankConfig.getChCode())) {
                        // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
                        bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(
                                base.getBankBusProd(), BisBankInterfaceChannel._09, base.getBank());
                        logger.error("BankExPayInteractServiceImpl快捷支付checkSms specialChCode: 1");
                    }
                }
                if ("2".equals(base.getSpecialChCode())) {
                    // 钱包天宜盈交易固定走民生代扣通道
                    if (!BisBankInterfaceChannel._11.toString().equals(bankConfig.getChCode())) {
                        // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
                        bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(
                                base.getBankBusProd(), BisBankInterfaceChannel._11, base.getBank());
                        logger.error("BankExPayInteractServiceImpl快捷支付certification specialChCode: 2");
                    }
                }
            }

            if (BisBankInterfaceChannel._14.value.equals(bankConfig.getChCode())) {
                // 银行产品空通道
                logger.error(base.getOrderId() + " BankExPayInteractServiceImpl checkSms获取银行产品空通道 ");
                result.setResultCode(ProcCodeConstants.PROC_CODE_100E6090);
                result.setSuccess(false);
                return result;
            }
            base.setBankIntrChann(BisBankInterfaceChannel.get(bankConfig.getChCode()));
            // 平台外部清算机构代码
            String outStlmCd = InitialSpringBeanName.getOutStlmCd(bankConfig.getChCode(), bankBusProd, base.getBank());
            base.setOutStlmCd(outStlmCd);
            // 获取SPRING加载的快捷BeanName
            String beanName = outStlmCd + "-" + "EXPAY";
            ExPayInteractRemoteService exPayService = (ExPayInteractRemoteService) SpringContextUtil.getBean(beanName);

            if (!BisPayCheckUtils.checkExternalOrderID(base.getOrderId())) {
                // 设置一级私钥路径
                base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
                // 设置一级私钥密码
                base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
                // 设置二级私钥路径
                base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
                // 设置二级私钥密码
                base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
                // 设置公钥路径
                base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
                // 设置商户号
                base.setMerID(bankConfig.getIntrMernum1());
                // 设置二级商户号
                base.setMerID2nd(bankConfig.getIntrMernum2());
                // 设置结算账户网点联行号
                base.setBranchCode(bankConfig.getBranchCode());
                // 设置银行支付地址
                base.setPayUrl(bankConfig.getPayUrl());
                // 设置支付后台通知地址
                base.setPayRuturnUrl(bankConfig.getPayRuturnUrl());
                // 设置支付后前通知地址
                base.setPayNotifyUrl(bankConfig.getPayNotifyUrl());
            }

            // 验证短信
            result = exPayService.checkSms(base);
            // 短信校验通过更新快捷流水表
            if (result.isSuccess() && (boolean) result.getModel("flag")) {
                bisExpayDtlService.updateSmsAuthDtl(base);
            }
            logger.error("BankExPayInteractServiceImpl验证短信请求返回处理对象：" + ToStringBuilder.reflectionToString(result));
        } catch (GopayException ex) {
            logger.error("BankExPayInteractServiceImpl checkSms error: ", ex);
            result.setResultCode(ex.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankExPayInteractServiceImpl checkSms error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }
    
 
    /**
     * 退款通知接口
     */
    public Result refundBack(ExPayBaseMessage base) {
        logger.error("BankExPayInteractServiceImpl快捷支付refundBack处理base对象：" + LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
        Result result = new Result();
        try{
            BankOrder bankOrder = new BankOrder();
            BankOrder oriBankOrder = new BankOrder();
            //获取退款订单
            bankOrder = bankOrderManager.getBankOrderById(base.getBankOrderId());
            // 原支付订单
            oriBankOrder = bankOrderManager.getBankOrderById(bankOrder.getOriOutOrderId());
            base.setOrderId(bankOrder.getOrderId());
            base.setAmount(bankOrder.getSendBankAmt());
            String beanName = "";
            //原支付的cps订单
            CpsGenMainOrder mainOrder = getMainOrder(oriBankOrder.getOrderId());
            // 获取SPRING加载的BeanName
            beanName = getBeanName(mainOrder, BisBankInterfaceChannel.get(oriBankOrder.getInterfaceChennelCode()),
                    BisBankBusinessProd.get(oriBankOrder.getBankBizProdCode()));
            
            /****************** 处理银行多次通知 begin ***********************/
            // 是否验签成功过
            if (StringUtils.equals(bankOrder.getOrderStatus(), BankOrderStatus.BANK_CALL_SUCCESS)) {
                result.setDefaultModel(true);
                result.setSuccess(true);
                return result;
            }
            // 是否验签失败过
            if (StringUtils.equals(bankOrder.getOrderStatus(), BankOrderStatus.VERIFY_FAIL)) {
                result.setDefaultModel(false);
                result.setSuccess(true);
                return result;
            }
            /************** 处理银行多次通知 end *******************/
            //退款返回验签
            ExPayInteractRemoteService exPayService = (ExPayInteractRemoteService) SpringContextUtil.getBean(beanName);
            result = exPayService.refundBack(base);
            
            if(result.isSuccess()&& (Boolean)result.getDefaultModel()){
                Map<String, String> param = (Map<String, String>) result.getModel("isNotifyCashier");
                if(result.isOrderStatus()){
                    String amt = (String) param.get("amt"); // 银行返回交易金额
                    if (bankOrder.getSendBankAmt() != null
                            && bankOrder.getSendBankAmt().compareTo(new BigDecimal(amt)) != 0) {
                        // 退款银行返回金额与平台上送金额不符
                        bankOrderManager.updateAmountError(bankOrder.getOrderId());
                        logger.error("退款银行【 " + beanName + "】返回处理结果：国付宝订单号【" + base.getOrderId() + "】金额比对异常");
                        result.setSuccess(false);
                        result.setResultCode(ProcCodeConstants.PROC_CODE_100E5079);
                        result.setErrorMsg("通知订单金额不一致");
                        return result;
                    }
                    bankOrderManager.updateBackSuccess(bankOrder.getOrderId());
                    logger.error("退款银行【 " + beanName + "】返回处理结果：国付宝订单号【" + base.getOrderId()+ "】验签成功，bis_bank_main_order表更新成功状态");
                }else{
                    // 退款失败更新失败原因
                    bankOrder.setRemark2((String) param.get("retMsg"));
                    bankOrderManager.updateBankOrder(bankOrder);
                    logger.error("退款银行【 " + beanName + "】返回处理结果：国付宝订单号【" + base.getOrderId() + "】验签成功，订单未成功");
                }
            }else {
                // 验签失败
                bankOrderManager.updateBackVerifyFail(bankOrder.getOrderId());
                logger.error("退款银行【 " + beanName + "】退款返回处理结果：国付宝订单号【" + base.getOrderId()+ "】验签失败，bis_bank_main_order表更新失败状态");
            }
        }catch(GopayException e){
            logger.error("BankExPayInteractServiceImpl refundBack error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        }catch(Exception ex){
            logger.error("BankExPayInteractServiceImpl refundBack error: ", ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }

    /**
     * 支付请求接口
     */
    @Override
    public Result payment(ExPayBaseMessage base) {
        // 日志输出隐藏信用卡cvv2
        ExPayBaseMessage logData = getPrintMsg(base);
        /**央行检测 要求身份照掩码处理 sj 2017-11-03*/
        logger.error("BankExPayInteractServiceImpl快捷支付payment处理base对象：" + LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(logData)));
        Result result = new Result();
        try {
            checkRequest(base);

            // 获取订单信息与银行信息
            CpsGenMainOrder mainOrder = getMainOrder(base.getOrderId());
            // 钱包充值交易，鉴权，发短信，验短信和支付时上送的订单号不一致，匹配要素时取鉴权的订单号，匹配通过后，重新赋值成支付的订单号
            String orderId = base.getOrderId();
            if (IntTxnCd._00500.value.equals(mainOrder.getGopayIntTxnCd())
                    && GatewaySource.GATEWAY_SOURCE_05.value.equals(mainOrder.getGatewaySource())
                    && StringUtils.isNotBlank(mainOrder.getRelevanceGopayOrderId())) {

                base.setOrderId(mainOrder.getRelevanceGopayOrderId());
            } else if (IntTxnCd._01732.value.equals(mainOrder.getGopayIntTxnCd())) {
                // add by huangcheng 跨境汇款充值订单验证原汇款订单号
                base.setOrderId(mainOrder.getRelevanceGopayOrderId());
            }
            // 基金，钱包老版本，08来源交易,手机钱包 一分钱支付 不走校验规则,后期统一调用委托代扣接口；委托代收支付、直接代收业务不走要素校验
            // IntTxnCd._02004.value.equals(mainOrder.getGopayIntTxnCd()) ||
            if (OLD_GOPAY.equals(base.getValidateCode())
                    || GatewaySource.GATEWAY_SOURCE_08.value.equals(mainOrder.getGatewaySource())
                    || IntTxnCd._01614.value.equals(mainOrder.getGopayIntTxnCd())
                    || BisBankBusinessProd._20.value.equals(base.getBankBusProd().value)
                    || BisBankBusinessProd._21.value.equals(base.getBankBusProd().value)) {
            } else {
                CpsGenReceiptOrder cpsGenReceiptOrder =cpsGeneralReceiptOrderQueryDAO.find(CpsGenReceiptOrder.class,base.getOrderId());
                if(cpsGenReceiptOrder != null && cpsGenReceiptOrder.getSmsAdvice()!= null && SmsAdviceEnum.MERCHANT_SEND.value.equals(cpsGenReceiptOrder.getSmsAdvice())){
                    //如果是商户发短信只校验要素信息，不匹配快捷流水状态
                    bisExpayDtlService.checkSendSmsCerElements(base);
                }else{
                 // 支付时对比和鉴权成功的要素是否匹配，是否经过短信授权
                    bisExpayDtlService.checkPayCerElements(base);
                }
                
            }

            base.setOrderId(orderId);

            if ("TBANK".equals(base.getBank())) {
                // 根据环境返回TBANK结果，生产返回失败其他环境返回成功
                if ("on".equals(bisConfig.get("BIS.TBANK.FLAG"))) {
                    // TBANK返回成功
                    result.setSuccess(true);
                    result.setModel("flag", true);
                } else {
                    // TBANK返回失败
                    result.setSuccess(true);
                    result.setModel("flag", false);
                }
                return result;
            }

            // 获取SPRING加载的BeanName
            String beanName = getBeanName(mainOrder, base.getBankIntrChann(), base.getBankBusProd());
            ExPayInteractRemoteService exPayService = (ExPayInteractRemoteService) SpringContextUtil.getBean(beanName);
            base.setBankOrderId(base.getOrderId());
            if (!BisPayCheckUtils.checkExternalOrderID(base.getOrderId())) {
                BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
                // boolean isbankRoute = false; // 是否自动路由标识
                // if (!"3".equals(base.getSpecialChCode())) {
                // // 基金交易跳过自动路由
                // isbankRoute = isRouteOrWhiteList(mainOrder.getMerId());
                // }

                if (isRouteOrWhiteList(mainOrder.getMerId())) {
                    // 增加银行自动路由开关 add by zhengxue
                    bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(),
                            base.getBankIntrChann(), base.getBank());
                } else {
                    // 获取银行接口通道配置信息
                    bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(),
                            base.getBank());
                    if ("1".equals(base.getSpecialChCode())) {
                        // 钱包交易固定走易宝通道
                        if (!BisBankInterfaceChannel._09.toString().equals(bankConfig.getChCode())) {
                            // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
                            bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(
                                    base.getBankBusProd(), BisBankInterfaceChannel._09, base.getBank());
                            logger.error("BankExPayInteractServiceImpl快捷支付payment specialChCode: 1");
                        }
                    }
                    if ("2".equals(base.getSpecialChCode())) {
                        // 钱包天宜盈交易固定走民生代扣通道
                        if (!BisBankInterfaceChannel._11.toString().equals(bankConfig.getChCode())) {
                            // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
                            bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(
                                    base.getBankBusProd(), BisBankInterfaceChannel._11, base.getBank());
                            logger.error("BankExPayInteractServiceImpl快捷支付certification specialChCode: 2");
                        }
                    }
                }

                // 设置一级私钥路径
                base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
                // 设置一级私钥密码
                base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
                // 设置二级私钥路径
                base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
                // 设置二级私钥密码
                base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
                // 设置公钥路径
                base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
                // 设置商户号
                base.setMerID(bankConfig.getIntrMernum1());
                // 设置二级商户号
                base.setMerID2nd(bankConfig.getIntrMernum2());
                // 设置结算账户网点联行号
                base.setBranchCode(bankConfig.getBranchCode());
                // 设置银行支付地址
                base.setPayUrl(bankConfig.getPayUrl());
                // 设置支付后台通知地址
                base.setPayRuturnUrl(bankConfig.getPayRuturnUrl());
                // 设置支付后前通知地址
                base.setPayNotifyUrl(bankConfig.getPayNotifyUrl());
            }

            // 校验银行订单不能为多条,此处以后修改
            List<BankOrder> bankOrders = bankOrderService.getBankOrdersByGopayOrderId(base.getOrderId());
            if (bankOrders != null && bankOrders.size() > 0) {
                result.setResultCode(ProcCodeConstants.PROC_CODE_100E5015);// 已存在相同的订单
                result.setSuccess(false);
                return result;
            }
            // 支付
            result = exPayService.payment(base);
            
            base.setBankOrderType(BankOrderType.GOPAY_BIS_ORDER);// 订单类型：新平台订单
            bankOrderService.addBankOrder(base);
            logger.error("BankExPayInteractServiceImpl支付请求返回处理对象：" + ToStringBuilder.reflectionToString(result));
        } catch (GopayException e) {
            logger.error("BankExPayInteractServiceImpl payment error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankExPayInteractServiceImpl payment error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }

    /**
     * 返回结果处理接口
     */
    @Override
    public Result verify(ExPayBaseMessage base) {
    	/**央行检测 要求身份照掩码处理 sj 2017-11-03*/
        logger.error("BankExPayInteractServiceImpl快捷支付verify银行返回处理base对象：" + LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
        Result result = new Result();
        try {
            if (base.getBankOrderId() == null || base.getBankOrderId().equals("")) {
                BankOrder bankOrder = new BankOrder();
                base.setOutStlmCd(base.getBank());
                BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
                // 银行自动路由修改支付返回无订单号订单,获取产品渠道方法(由获取当前生效渠道改为根据银行、产品、渠道码获取) add by
                // zhengxue
                bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(),
                        base.getBankIntrChann(), base.getBank());

                if (bankConfig != null) {
                    // 设置一级私钥路径
                    base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
                    // 设置一级私钥密码
                    base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
                    // 设置二级私钥路径
                    base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
                    // 设置二级私钥密码
                    base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
                    // 设置公钥路径
                    base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
                }

                // 验签
                String beanName = getBankBeanName(base); // 只返回密文银行获取beanName
                ExPayInteractRemoteService exPayService = (ExPayInteractRemoteService) SpringContextUtil
                        .getBean(beanName);
                result = exPayService.verify(base);
                base = (ExPayBaseMessage) result.get("res");
                logger.error("BankExPayInteractServiceImpl验签返回处理对象：" + ToStringBuilder.reflectionToString(result));
                if (result.isSuccess() && (Boolean) result.getDefaultModel()) {
                    // 验签成功
                    if (result.isOrderStatus()) {
                        bankOrder = bankOrderManager.getBankOrderById(base.getBankOrderId());
                        Map<String, String> param = (Map<String, String>) result.getModel("isNotifyCashier");
                        String amt = (String) param.get("amt"); // 银行返回交易金额
                        if (bankOrder.getSendBankAmt() != null
                                && bankOrder.getSendBankAmt().compareTo(new BigDecimal(amt)) != 0) {
                            // 银行返回金额与平台上送金额不符
                            bankOrderManager.updateAmountError(bankOrder.getOrderId());
                            logger.error("银行【 " + beanName + "】返回处理结果：国付宝订单号【" + base.getOrderId() + "】金额比对异常");
                            result.setSuccess(false);
                            result.setResultCode(ProcCodeConstants.PROC_CODE_100E5079);
                            result.setErrorMsg("通知订单金额不一致");
                            return result;
                        }
                        bankOrderManager.updateBackSuccess(base.getOrderId());
                        logger.error("银行【 " + beanName + "】返回处理结果：订单号【" + base.getOrderId()
                                + "】支付成功，bis_bank_main_order表更新成功状态");
                    } else {
                        logger.error("银行【 " + beanName + "】返回处理结果：订单号【" + base.getOrderId() + "】状态失败");
                    }
                } else {
                    // 验签失败
                    bankOrderManager.updateBackVerifyFail(base.getOrderId());
                    logger.error("银行【 " + beanName + "】返回处理结果：订单号【" + base.getOrderId()
                            + "】验签失败，bis_bank_main_order表更新失败状态");
                }
                logger.error("BankExPayInteractServiceImpl验签返回处理base对象：" + ToStringBuilder.reflectionToString(base));

                bankOrder = bankOrderManager.getBankOrderById(base.getBankOrderId());
                base.setOrderId(bankOrder.getOrderId());
                // 是否验签成功过
                if (StringUtils.equals(bankOrder.getOrderStatus(), BankOrderStatus.BANK_CALL_SUCCESS)) {
                    result.setDefaultModel(true);
                    result.setSuccess(true);
                }
                return result;
            }

            BankOrder bankOrder = null;
            bankOrder = bankOrderManager.getBankOrderById(base.getBankOrderId());
            // 自动路由需使用主订单表对象,挪到此处获取 add by zhengxue
            CpsGenMainOrder mainOrder = new CpsGenMainOrder();

            String bankBizProdCode = bankOrder.getBankBizProdCode();
            base.setOrderId(bankOrder.getOrderId());
            base.setAmount(bankOrder.getSendBankAmt());
            if (BisBankBusinessProd._05.value.equals(bankBizProdCode)) {
                base.setBankBusProd(BisBankBusinessProd._05);
            } else if (BisBankBusinessProd._15.value.equals(bankBizProdCode)) {
                base.setBankBusProd(BisBankBusinessProd._15);
            } else {
                throw new GopayException(ProcCodeConstants.PROC_CODE_100E1141);
            }
            // 如果为外部平台订单
            if (BisPayCheckUtils.checkExternalOrderID(bankOrder.getOrderId())) {
                // 获取外部订单交易对象
                BisPayMessage bisPayMessage = bisPayMessageManager
                        .getBisPayMessageByGopayOrderId(bankOrder.getOrderId());
                // 如果使用外部平台自己的订单
                if (bisPayMessage.getIsThroughBis().equals("1")) {
                    base.setOutStlmCd(base.getBank());
                    BisBankMerchant bisBankMerchant = bisExternalPlatformService.getBankMerchant(
                            bisPayMessage.getPlatformId(), bankOrder.getBankCode(), base.getBankBusProd().value);
                    // 设置一级私钥路劲
                    base.setPrivateKeyPath(bisBankMerchant.getIntrMerPravkeyPath());
                    // 设置一级私钥密码
                    base.setPrivatePwd(bisBankMerchant.getIntrMerPravkeyPwd());
                    // 设置二级私钥路径
                    base.setPrivateKeyPath2nd(bisBankMerchant.getIntrMer2ndPravkeyPath());
                    // 设置二级私钥密码
                    base.setPrivatePwd2nd(bisBankMerchant.getIntrMer2ndPravkeyPwd());
                    // 设置公钥路径
                    base.setPublicKeyPath(bisBankMerchant.getIntrBankPubkeyPath());
                } else {
                    base.setOutStlmCd(base.getBank());
                    BaseBisBankExtConfig bankConfig = bisBankExtConfigManager
                            .findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(), bankOrder.getBankCode());
                    // 设置一级私钥路径
                    base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
                    // 设置一级私钥密码
                    base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
                    // 设置二级私钥路径
                    base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
                    // 设置二级私钥密码
                    base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
                    // 设置公钥路径
                    base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
                }
            } else {
                // 获取订单信息与银行信息
                mainOrder = getMainOrder(bankOrder.getOrderId());
                base.setOutStlmCd(base.getBank());
                BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
                if (isRouteOrWhiteList(mainOrder.getMerId())) {
                    // 增加银行自动路由开关 add by zhengxue
                    bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(),
                            BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode()), bankOrder.getBankCode());
                } else {
                    bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(),
                            bankOrder.getBankCode());
                }
                // 设置商户号
                base.setMerID(bankConfig.getIntrMernum1());
                // 设置一级私钥路径
                base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
                // 设置一级私钥密码
                base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
                // 设置二级私钥路径
                base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
                // 设置二级私钥密码
                base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
                // 设置公钥路径
                base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
            }
            String beanName = "";

            // 如果定单为外部平台
            if (BisPayCheckUtils.checkExternalOrderID(bankOrder.getOrderId())) {
                beanName = getExternalBeanName(base, bankOrder);
            } else {
                // 获取订单信息与银行信息
                mainOrder = getMainOrder(bankOrder.getOrderId());
                // 获取SPRING加载的BeanName
                beanName = getBeanName(mainOrder, BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode()),
                        BisBankBusinessProd.get(bankOrder.getBankBizProdCode()));
            }

            /****************** 处理银行多次通知 begin ***********************/
            // 是否验签成功过
            if (StringUtils.equals(bankOrder.getOrderStatus(), BankOrderStatus.BANK_CALL_SUCCESS)) {
                ExPayInteractRemoteService bankService = (ExPayInteractRemoteService) SpringContextUtil
                        .getBean(beanName);
                result = bankService.verify(base);
                //update by wjq 2017/08/10
//                MtPayInteractRemoteService bankService = (MtPayInteractRemoteService) SpringContextUtil
//                        .getBean(beanName);
//                result = bankService.bankBack(base);
                result.setDefaultModel(true);
                result.setSuccess(true);
                return result;
            }
            // 是否验签失败过
            if (StringUtils.equals(bankOrder.getOrderStatus(), BankOrderStatus.VERIFY_FAIL)) {
                result.setDefaultModel(false);
                result.setSuccess(true);
                return result;
            }
            /************** 处理银行多次通知 end *******************/
            // 验签
            ExPayInteractRemoteService exPayService = (ExPayInteractRemoteService) SpringContextUtil.getBean(beanName);
            result = exPayService.verify(base);

            if (base.isFront()) {
                // 前台通知不更新银行流水状态，直接返回
                return result;
            }
            if (result.isSuccess() && (Boolean) result.getDefaultModel()) {
                // 验签成功
                if (result.isOrderStatus()) {
                    Map<String, String> param = (Map<String, String>) result.getModel("isNotifyCashier");
                    String amt = (String) param.get("amt"); // 银行返回交易金额
                    if (bankOrder.getSendBankAmt() != null
                            && bankOrder.getSendBankAmt().compareTo(new BigDecimal(amt)) != 0) {
                        // 银行返回金额与平台上送金额不符
                        bankOrderManager.updateAmountError(bankOrder.getOrderId());
                        logger.error("银行【 " + beanName + "】返回处理结果：国付宝订单号【" + base.getOrderId() + "】金额比对异常");
                        result.setSuccess(false);
                        result.setResultCode(ProcCodeConstants.PROC_CODE_100E5079);
                        result.setErrorMsg("通知订单金额不一致");
                        return result;
                    }

                    bankOrderManager.updateBackSuccess(bankOrder.getOrderId());
                    //add by wjq 2017/08/09
                    if(BisBankInterfaceChannel._18.value.equals(bankOrder.getInterfaceChennelCode())){
                      //网联通道支付成功后，需保留收款银行订单号，退款时备用
                        bankOrder.setBankOrderId(base.getBankReturnOrderId());
                        bankOrderManager.updateBankOrder(bankOrder);
                    }                    
                    logger.error("银行【 " + beanName + "】返回处理结果：国付宝订单号【" + base.getOrderId()
                            + "】支付成功，bis_bank_main_order表更新成功状态");
                } else {
                    logger.error("银行【 " + beanName + "】返回处理结果：国付宝订单号【" + base.getOrderId()
                            + "】验签失败，bis_bank_main_order表更新失败状态");
                }
            } else {
                // 验签失败
                bankOrderManager.updateBackVerifyFail(bankOrder.getOrderId());
                logger.error(
                        "银行【 " + beanName + "】返回处理结果：国付宝订单号【" + base.getOrderId() + "】验签失败，bis_bank_main_order表更新失败状态");
            }

        } catch (GopayException e) {
            logger.error("BankInteractServiceImpl bankBack error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankInteractServiceImpl bankBack error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }

    /**
     * 查询订单
     */
    @Override
    public Result queryOrder(ExPayBaseMessage base) {
    	/**央行检测 要求身份照掩码处理 sj 2017-11-03*/
        logger.error("BankExPayInteractServiceImpl快捷支付query查询处理base对象：" + LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
        Result result = new Result();
        try {
            CpsGenMainOrder mainOrder = getMainOrder(base.getOrderId());
            // 获取SPRING加载的BeanName
            String outStlmId = getOutStlmId(mainOrder, base.getBankIntrChann(), base.getBankBusProd());
            base.setOutStlmCd(outStlmId);
            base.setAmount(mainOrder.getTotalOrderAmt());
            if (mainOrder.getSettleAmt() != null) {
                // 发送银行金额取结算金额,若为空则取总金额字段
                base.setAmount(mainOrder.getSettleAmt());
            }
            BisBankInterfaceChannel channel = null;
            BisBankBusinessProd prod = null;
            String beanName = "";
            if (BisBankBusinessProd._12.value.equals(base.getBankBusProd().value)) {
                // 获取原银行支付订单
                BankOrder oriBankOrder = bankOrderManager.getBankOrderById(base.getTkOriBankOrderId());
                if (oriBankOrder == null) {
                    throw new GopayException(ProcCodeConstants.PROC_CODE_100E5041);
                }
                channel = BisBankInterfaceChannel.get(oriBankOrder.getInterfaceChennelCode());
                prod = BisBankBusinessProd.get(oriBankOrder.getBankBizProdCode());
                // 获取原银行支付主订单
                CpsGenMainOrder oriMainOrder = getMainOrder(oriBankOrder.getOrderId());
                // 退款查询
                beanName = getBeanName(oriMainOrder, channel, prod);
            } else {
                channel = base.getBankIntrChann();
                prod = base.getBankBusProd();
                // 查询
                beanName = getBeanName(mainOrder, base.getBankIntrChann(), base.getBankBusProd());
            }
            ExPayInteractRemoteService exPayService = (ExPayInteractRemoteService) SpringContextUtil.getBean(beanName);
            if (!BisPayCheckUtils.checkExternalOrderID(base.getOrderId())) {
                // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
                BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(prod,
                        channel, base.getBank());
                // 设置一级私钥路径
                base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
                // 设置一级私钥密码
                base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
                // 设置二级私钥路径
                base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
                // 设置二级私钥密码
                base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
                // 设置公钥路径
                base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
                // 设置商户号
                base.setMerID(bankConfig.getIntrMernum1());
                // 设置二级商户号
                base.setMerID2nd(bankConfig.getIntrMernum2());
                // 设置结算账户网点联行号
                base.setBranchCode(bankConfig.getBranchCode());
                // 设置银行查询地址
                base.setQueryUrl(bankConfig.getQueryUrl());
            }
            result = exPayService.queryOrder(base);
            logger.error("BankExPayInteractServiceImpl银行查询返回base对象：" + ToStringBuilder.reflectionToString(result));
        } catch (GopayException e) {
            logger.error("BankExPayInteractServiceImpl query error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankExPayInteractServiceImpl query error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }

    /**
     * 查询是否需要调用鉴权接口
     */
    @Override
    public Result queryNeedCert(ExPayBaseMessage base) {

        // 日志输出隐藏信用卡cvv2
        ExPayBaseMessage logData = getPrintMsg(base);
        /**央行检测 要求身份照掩码处理 sj 2017-11-03*/
        logger.error(
                "BankExPayInteractServiceImpl   queryNeedCert处理base对象：" + LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(logData)));
        Result result = new Result();
        try {
            checkRequest(base);
            // 获取订单信息与银行信息
            CpsGenMainOrder mainOrder = getMainOrder(base.getOrderId());

            if ("TBANK".equals(base.getBank())) {
                // 根据环境返回TBANK结果，生产返回失败其他环境返回成功
                result.setModel("NeedMark", QueryNeedCertConstants.QUERY_RESULT_NONEED);
                result.setSuccess(true);
                return result;
            }

            // 获取SPRING加载的BeanName
            String beanName = getBeanName(mainOrder, base.getBankIntrChann(), base.getBankBusProd());
            ExPayInteractRemoteService exPayService = (ExPayInteractRemoteService) SpringContextUtil.getBean(beanName);
            base.setBankOrderId(base.getOrderId());
            if (!BisPayCheckUtils.checkExternalOrderID(base.getOrderId())) {
                BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
                if (isRouteOrWhiteList(mainOrder.getMerId())) {
                    // 增加银行自动路由开关 add by zhengxue
                    bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(),
                            base.getBankIntrChann(), base.getBank());
                } else {
                    // 获取银行接口通道配置信息
                    bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(),
                            base.getBank());
                }

                // 设置一级私钥路径
                base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
                // 设置一级私钥密码
                base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
                // 设置二级私钥路径
                base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
                // 设置二级私钥密码
                base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
                // 设置公钥路径
                base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
                // 设置商户号
                base.setMerID(bankConfig.getIntrMernum1());
                // 设置二级商户号
                base.setMerID2nd(bankConfig.getIntrMernum2());
                // 设置结算账户网点联行号
                base.setBranchCode(bankConfig.getBranchCode());
                // 设置银行支付地址
                base.setPayUrl(bankConfig.getPayUrl());
                // 设置支付后台通知地址
                base.setPayRuturnUrl(bankConfig.getPayRuturnUrl());
                // 设置支付后前通知地址
                base.setPayNotifyUrl(bankConfig.getPayNotifyUrl());
            }
            // 支付
            result = exPayService.queryNeedCert(base);
            logger.error(
                    "BankExPayInteractServiceImpl  queryNeedCert返回处理对象：" + ToStringBuilder.reflectionToString(result));
        } catch (GopayException e) {
            logger.error("BankExPayInteractServiceImpl queryNeedCert error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankExPayInteractServiceImpl queryNeedCert error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }

    /**
     * 获取订单信息
     * 
     * @param orderId
     * @return
     * @throws GopayException
     */
    private CpsGenMainOrder getMainOrder(String orderId) throws GopayException {
        if (orderId == null || "".equals(orderId)) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E5041);
        }
        // 获取主订单表
        CpsGenMainOrder mainOrder = mainOrderQuery.get(orderId);
        if (mainOrder == null) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E5041);
        }
        return mainOrder;
    }

    /**
     * 获取SPRING加载的BeanName
     * 
     * <pre>
     * BeanName规范:银行编码-交易类型，如TBANK-B2B
     * </pre>
     * 
     * @param mainOrder
     *            订单信息
     * @param inChann
     *            银行信息
     * @param bankBusProd
     * @return
     * @throws GopayException
     */
    private String getBeanName(CpsGenMainOrder mainOrder, BisBankInterfaceChannel inChann,
            BisBankBusinessProd bankBusProd) throws GopayException {
        String beanSuffix = TradeType.getOrderTrandType(mainOrder.getPayChannel());
        String outStlmId = getOutStlmId(mainOrder, inChann, bankBusProd);
        String beanName = outStlmId + "-" + beanSuffix;
        return beanName;
    }

    /**
     * 获取SPRING加载的BeanName
     * 
     * <pre>
     * BeanName规范:银行编码-交易类型，如TBANK-B2B
     * </pre>
     * 
     * @param message
     * @param bankOrder
     * @return
     * @throws GopayException
     */
    private String getExternalBeanName(BaseMessage message, BankOrder bankOrder) throws GopayException {
        String beanName = "";
        if (bankOrder != null) {
            String beanSuffix = "";
            String outStlmId = "";
            String chennelCodeValue = BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode()).value;
            String bankBizProdCode = BisBankBusinessProd.get(bankOrder.getBankBizProdCode()).value;
            if (BisBankBusinessProd._05.value.equals(bankBizProdCode)
                    || BisBankBusinessProd._15.value.equals(bankBizProdCode)) {
                beanSuffix = "EXPAY";
            } else {
                throw new GopayException(ProcCodeConstants.PROC_CODE_100E1141);
            }
            if (StringUtils.equals(TradeType.TRADE_TYPE_EXPAY, beanSuffix)) {
                outStlmId = InitialSpringBeanName.getOutStlmCd(chennelCodeValue, bankBizProdCode,
                        bankOrder.getBankCode());
            } else {
                outStlmId = bankOrder.getBankCode();
            }
            message.setBank(outStlmId);
            beanName = outStlmId + "-" + beanSuffix;
            return beanName;
        } else {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E1141);
        }
    }

    /**
     * 获取SPRING加载的BeanName(银行返回密文) BeanName规范:银行编码-交易类型，如TBANK-B2B
     * 
     * @param base
     * @return String
     * @throws GopayException
     */
    private String getBankBeanName(BaseMessage base) throws GopayException {
        if (StringUtils.equals(BankConstants.BANK_LOGO_YEEPAY, base.getBank()) && base instanceof YeePayExPayMessage) {
            return "YEEPAY-EXPAY";
        } else if (StringUtils.equals(BankConstants.BANK_LOGO_YSPAY, base.getBank())
                && base instanceof YspayAdPayMessage) {
            return "YSPAY-EXPAY";
        } else {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E7022);
        }
    }

    private String getOutStlmId(CpsGenMainOrder mainOrder, BisBankInterfaceChannel inChann,
            BisBankBusinessProd bankBusProd) throws GopayException {
        String beanSuffix = TradeType.getOrderTrandType(mainOrder.getPayChannel());
        String outStlmId = "";
        if (StringUtils.equals(TradeType.TRADE_TYPE_EXPAY, beanSuffix)) {
            outStlmId = InitialSpringBeanName.getOutStlmCd(inChann.value, bankBusProd.value, mainOrder.getOutStlmId());
        } else {
            outStlmId = mainOrder.getOutStlmId();
        }
        return outStlmId;
    }

    /**
     * 基础参数检查
     * 
     * @param request
     * @throws GopayException
     */
    private void checkRequest(ExPayBaseMessage request) throws GopayException {
        String phoneNo = request.getMediaId();
        String cardHolder = request.getCardHolder();
        String cardNo = request.getCardNo();
        String bank = request.getBank();
        String cidNo = request.getIdentityCode().trim();
        // String cidType = request.getIdentityType();
        String bankBusProd = request.getBankBusProd().value;

        logger.error("-----------bankBusProd----------------" + bankBusProd);
        if (StringUtils.isBlank(bankBusProd)) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E7014);
        }
        if (StringUtils.isBlank(phoneNo)) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6073);
        }
        if (StringUtils.isBlank(cardHolder)) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6072);
        }
        if (StringUtils.isBlank(cardNo)) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6069);
        }
        if (StringUtils.isBlank(bank)) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E1135);
        }
        if (StringUtils.isBlank(cidNo)) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6075);
        }
        if (!CertNoVerifyUtil.verify(cidNo)) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6075);
        }
    }

    /**
     * 校验银行业务产品是否支持该通道
     * 
     * @param config
     * @param bankBusProd
     * @throws GopayException
     */
    private void checkBankBussProdAndIntrChan(BaseBisBankExtConfig config, String bankBusProd) throws GopayException {
        if (null == config) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E7021);
        }
        String intrChann = config.getChCode();// 接口通道
        bankIntrChannConfService.checkBankBussProdAndIntrChan(intrChann, bankBusProd);
    }

    /**
     * 快捷对象输出，隐藏信用卡cvv2
     * 
     * @param baseMsg
     * @return
     */
    private ExPayBaseMessage getPrintMsg(ExPayBaseMessage baseMsg) {
        ExPayBaseMessage logData = new ExPayBaseMessage();
        BeanUtils.copyProperties(baseMsg, logData);
        if (logData.getCvv2() == null || "".equals(logData.getCvv2())) {
            //
        } else {
            logData.setCvv2("***");
        }
        return logData;
    }

    @Override
    public Result sign(ExPayBaseMessage base) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result treatyQuery(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result cancel(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result refund(ExPayBaseMessage baseMsg) {
    	/**央行检测 要求身份照掩码处理 sj 2017-11-03*/
        logger.error("BankExPayInteractServiceImpl 银行退款处理base对象：" + LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(baseMsg)));
        ExPayBaseMessage base = new ExPayBaseMessage();
        BeanUtils.copyProperties(baseMsg, base);
        Result result = new Result();
        try {
            /**
             * 获取原支付订单信息与银行信息
             */
            CpsGenMainOrder mainOrder = getMainOrder(base.getTkOriOrderId());

            /**
             * 获取原支付银行订单
             */
            List<BankOrder> bankOrders = bankOrderService.getBankOrdersByGopayOrderId(base.getTkOriOrderId());
            BankOrder bankOrder = bankOrders.get(0);
            // 退款订单
            BankOrder refundBankOrder = bankOrderService.getBankOrderById(base.getBankOrderId());

            if (!isSendTkOrder(bankOrder.getOutOrderId())) {
                /**
                 * 已存在处理中退款交易
                 */
                result.setResultCode(ProcCodeConstants.PROC_CODE_100E6089);
                result.setSuccess(false);
                return result;
            }
            BisBankInterfaceChannel channel = BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode());
            BisBankBusinessProd prod = BisBankBusinessProd.get(bankOrder.getBankBizProdCode());

            /**
             * 获取SPRING加载的BeanName
             */
            String outStlmId = InitialSpringBeanName.getOutStlmCd(channel.value, prod.value, bankOrder.getBankCode());
            base.setOutStlmCd(outStlmId);
            /**
             * 退款金额
             */
            base.setAmount(baseMsg.getAmount());
            String beanName = getBeanName(mainOrder, channel, prod);
            ExPayInteractRemoteService exPayService = (ExPayInteractRemoteService) SpringContextUtil.getBean(beanName);
            // 退款银行订单号
            base.setTkOriBankOrderId(bankOrder.getOutOrderId());// 原订单号
            base.setSpecial4(DateUtils.formatDate(bankOrder.getSendBankTm(),DateUtils.DEFAULT_PATTERN));//原订单发送银行时间
            base.setBankBusProd(BisBankBusinessProd._12); // 退款
            base.setBankIntrChann(channel);
            base.setBank(bankOrder.getBankCode());
            base.setBankOrderType(BankOrderType.GOPAY_BIS_ORDER);// 订单类型：新平台订单
            base.setBankReturnOrderId(bankOrder.getBankOrderId());

            if (!BisPayCheckUtils.checkExternalOrderID(base.getOrderId())) {
                // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
                BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(prod,
                        channel, base.getBank());
                // 设置一级私钥路径
                base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
                // 设置一级私钥密码
                base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
                // 设置二级私钥路径
                base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
                // 设置二级私钥密码
                base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
                // 设置公钥路径
                base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
                // 设置商户号
                base.setMerID(bankConfig.getIntrMernum1());
                // 设置二级商户号
                base.setMerID2nd(bankConfig.getIntrMernum2());
                // 设置结算账户网点联行号
                base.setBranchCode(bankConfig.getBranchCode());
                // 设置银行查询地址
                base.setQueryUrl(bankConfig.getQueryUrl());
                // 设置银行支付地址
                base.setPayUrl(bankConfig.getPayUrl());
                // 设置支付后台通知地址
                base.setPayRuturnUrl(bankConfig.getPayRuturnUrl());
                // 设置支付后前通知地址
                base.setPayNotifyUrl(bankConfig.getPayNotifyUrl());
            }
            // 退款
            result = exPayService.refund(base);

            // 更新退款订单状态
            bankResUpdateOrder(result, refundBankOrder);

            // 如果银行同步返回退款处理结果，进行后续处理
            if ((BisBankInterfaceChannel._00.value.equals(base.getBankIntrChann().value)&& BankConstants.BANK_LOGO_CITIC.equals(base.getOutStlmCd()))
                    ||(BisBankInterfaceChannel._18.value.equals(base.getBankIntrChann().value))) {

                dealOrderAfterRefund(base, result);
            }

            logger.error("BankExPayInteractServiceImpl银行退款返回base对象：" + ToStringBuilder.reflectionToString(result));
        } catch (GopayException e) {
            logger.error("BankExPayInteractServiceImpl refund error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankExPayInteractServiceImpl refund error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    	/*logger.error("BankExPayInteractServiceImpl 银行退款处理base对象：" + ToStringBuilder.reflectionToString(baseMsg));
    	PabExPayMessage base=new PabExPayMessage();
        BeanUtils.copyProperties(baseMsg, base);
        Result result = new Result();
        try {
        	*//**
        	 * 获取原支付订单信息与银行信息
        	 *//*
            CpsGenMainOrder mainOrder = getMainOrder(baseMsg.getTkOriOrderId());
            *//**
             * 获取原支付银行订单
             *//*
            List<BankOrder> bankOrders = bankOrderService.getBankOrdersByGopayOrderId(baseMsg.getTkOriOrderId());
            BankOrder bankOrder = bankOrders.get(0);
            logger.error("退款发起  bankorder------"+ToStringBuilder.reflectionToString(bankOrder));
            if (!isSendTkOrder(bankOrder.getOutOrderId())) {
                *//**
                 * 已存在处理中退款交易
                 *//*
                result.setResultCode(ProcCodeConstants.PROC_CODE_100E6089);
                result.setSuccess(false);
                return result;
            }
            BisBankInterfaceChannel channel = BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode());
            BisBankBusinessProd prod = BisBankBusinessProd.get(bankOrder.getBankBizProdCode());

            *//**
             * 获取SPRING加载的BeanName
             *//*
            String outStlmId = InitialSpringBeanName.getOutStlmCd(channel.value, prod.value,bankOrder.getBankCode());
            base.setOutStlmCd(outStlmId);
            *//**
             * 订单总金额
             *//*
            base.setAmount(mainOrder.getTotalOrderAmt());
            String beanName = getBeanName(mainOrder,channel,prod);

            ExPayInteractRemoteService exPayService = (ExPayInteractRemoteService) SpringContextUtil.getBean(beanName);
            // 退款银行订单号
            base.setBankOrderId(base.getOrderId());
            base.setTkOriBankOrderId(bankOrder.getOutOrderId());
            base.setBankBusProd(BisBankBusinessProd._12); // 退款
            base.setBankIntrChann(channel);
            base.setBank(bankOrder.getBankCode());
            base.setBankOrderType(BankOrderType.GOPAY_BIS_ORDER);// 订单类型：新平台订单
            if (!BisPayCheckUtils.checkExternalOrderID(base.getOrderId())) {
                // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
                BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(
                        prod, channel, base.getBank());
                // 设置一级私钥路径
                base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
                // 设置一级私钥密码
                base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
                // 设置二级私钥路径
                base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
                // 设置二级私钥密码
                base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
                // 设置公钥路径
                base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
                // 设置商户号
                base.setMerID(bankConfig.getIntrMernum1());
                // 设置二级商户号
                base.setMerID2nd(bankConfig.getIntrMernum2());
                // 设置结算账户网点联行号
                base.setBranchCode(bankConfig.getBranchCode());
                // 设置银行查询地址
                base.setQueryUrl(bankConfig.getQueryUrl());
            }
            *//**
             *  保存退款订单
             *//*
            bankOrderService.addBankOrder(base);
            // 退款
            result = exPayService.refund(base);
            logger.error("BankExPayInteractServiceImpl银行退款返回base对象：" + ToStringBuilder.reflectionToString(result));
        } catch (GopayException e) {
            logger.error("BankExPayInteractServiceImpl refund error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankExPayInteractServiceImpl refund error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;*/
    }

    /**
     * 银行相应更新退款订单
     * 
     * @param result
     * @param bankOrder
     */
    private void bankResUpdateOrder(Result result, BankOrder bankOrder) {
        bankOrder = bankOrderService.getBankOrderById(bankOrder.getOutOrderId());
        // 银行订单状态
        String status = BankOrderStatus.PROCESS;// 进行中状态，等待银行异步通知

        bankOrder.setOrderStatus(status);
        bankOrder.setLastUpdTs(new Date());
        try {
            bankOrderService.updateBankOrder(bankOrder);
        } catch (StaleObjectStateException e) {
            Date finishTime = bankOrder.getTranFinishTime();
            bankOrder = bankOrderService.getBankOrderById(bankOrder.getOutOrderId());
            bankOrder.setOrderStatus(status);
            bankOrder.setLastUpdTs(new Date());
            if (finishTime != null) {
                bankOrder.setTranFinishTime(finishTime);
            }
            bankOrderService.updateBankOrder(bankOrder);
        }
    }

    /**
     * 退款后的订单操作
     * 
     * @param exPayMsg
     * @param result
     */
    private void dealOrderAfterRefund(ExPayBaseMessage exPayMsg, Result result) throws GopayException{

        try {
            if (!result.isSuccess()) {// 处理失败
                logger.error("BankExPayInteractServiceImpl dealOrderAfterRefund resultCode:" + result.getResultCode());
                return;
            }

            Map<String, String> param = new HashMap<String, String>();
            BankOrder bankOrder = null;
            bankOrder = bankOrderManager.getBankOrderById(exPayMsg.getBankOrderId());
            if (bankOrder == null) {
                throw new GopayException(ProcCodeConstants.PROC_CODE_100E5041);
            }
            param = (Map<String, String>) result.getModel("isNotifyCashier");
            /**央行检测 要求身份照掩码处理 sj 2017-11-03*/
            logger.error("BankExPayInteractServiceImpl refund resMsg: " + LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(exPayMsg)));
            if ((Boolean) result.getDefaultModel()) {
                String retMsg = param.get("retMsg"); // 订单信息描述
                if(exPayMsg.getTransBatchNo()!=null){
                	bankOrder.setTransBatchNo(exPayMsg.getTransBatchNo());
                	bankOrderManager.updateBankOrder(bankOrder);
                }
                if (result.isOrderStatus()) {
                    // 退款成功
                    String amt = (String) param.get("amt"); // 银行返回交易金额
                    if (bankOrder.getSendBankAmt() != null
                            && bankOrder.getSendBankAmt().compareTo(new BigDecimal(amt)) != 0) {
                        // 银行返回金额与平台上送金额不符
                        bankOrderManager.updateAmountError(param.get("orderId"));
                        logger.error(exPayMsg.getOutStlmCd() + " BankExPayInteractServiceImpl 退款返回处理结果：国付宝订单号【"
                                + param.get("orderId") + "】金额比对异常");
                        SendSmsUtils.sendSmsErr(smsConfig.get("switch"), smsConfig.get("mobile"),
                                "注意!!!退款订单金额不一致,银行:" + exPayMsg.getOutStlmCd() + "orderId:" + param.get("orderId"));
                        return;
                    }
                    bankOrderManager.updateBackSuccess(param.get("orderId"));
                    logger.error(exPayMsg.getOutStlmCd() + " BankExPayInteractServiceImpl退款返回处理结果：国付宝订单号【"
                            + param.get("orderId") + "】退款成功，bis_bank_main_order表更新成功状态");

                    param.put("sign", signRes(param));
                    logger.error("bis refund notify cashier: " + param);
                    /*notifyCashier.submit(param);*/ //生产优化10期 lx 2017-9-30 16:23:37
                    cashierBgNotifyRemoteService.callBgNotify(param);
                } else if (result.isOrderFail()) {
                    // 订单明确返回退款失败
                    bankOrder.setOrderStatus(BankOrderStatus.ORDER_FAIL);
                    bankOrderManager.updateBankOrder(bankOrder);
                    logger.error(exPayMsg.getOutStlmCd() + " BankExPayInteractServiceImpl退款返回处理结果：国付宝订单号【"
                            + param.get("orderId") + "】退款失败");

                    // 快捷支付订单处理银行返回失败时， 记录银行响应的错误码和错误描述 add by liuyong 20170216
                    errOrderRecordService.saveOrderErrorMsg(exPayMsg.getOrderId(), result.getResultCode(), retMsg);
                    logger.error(exPayMsg.getOutStlmCd() + " BankExPayInteractServiceImpl退款返回处理结果：国付宝订单号【"
                            + exPayMsg.getOrderId() + "】失败，银行返回错误码和错误信息为【" + result.getResultCode() + "===" + retMsg
                            + "】");
                    param.put("sign", signRes(param));
                    logger.error("bis expay refund cashier: " + param);
                    /*notifyCashier.submit(param);*/ //生产优化10期 lx 2017-9-30 16:23:37
                    cashierBgNotifyRemoteService.callBgNotify(param);
                } else {
                    // 快捷支付退款订单处理银行返回失败时， 记录银行响应的错误码和错误描述 add by liuyong
                    // 20170216
                    errOrderRecordService.saveOrderErrorMsg(exPayMsg.getOrderId(), result.getResultCode(), retMsg);
                    logger.error(exPayMsg.getOutStlmCd() + " BankExPayInteractServiceImpl退款返回处理结果：国付宝订单号【"
                            + exPayMsg.getOrderId() + "】失败，银行返回错误码和错误信息为【" + result.getResultCode() + "===" + retMsg
                            + "】");
                    logger.error(exPayMsg.getOutStlmCd() + " BankExPayInteractServiceImpl退款返回处理结果：国付宝订单号【"
                            + exPayMsg.getOrderId() + "】验签成功订单退款未成功");
                }
            } else {
                bankOrderManager.updateBackVerifyFail(exPayMsg.getOrderId());
                logger.error(exPayMsg.getOutStlmCd() + " BankExPayInteractServiceImpl退款返回处理结果：国付宝订单号【"
                        + exPayMsg.getOrderId() + "】验签失败，bis_bank_main_order表更新失败状态");
            }

        } catch (GopayException e) {
            logger.error("BankExPayInteractServiceImpl dealOrderAfterRefund gopayException: ", e);
        } catch (Exception e) {
            logger.error("BankExPayInteractServiceImpl dealOrderAfterRefund exception: ", e);
        }

    }

    /**
     * 通知cashier签名
     * 
     * @param res
     * @return
     */
    public String signRes(Map res) {
        StringBuffer sign = new StringBuffer();
        String orderId = (String) res.get("orderId");
        String amt = (String) res.get("amt");
        String retCode = (String) res.get("retCode");
        String retMsg = (String) res.get("retMsg");
        String payStatus = (String) res.get("payStatus");
        String notifyNum = (String) res.get("notifyNum");
        String cardType = (String) res.get("cardType");
        sign.append(orderId).append("|");
        sign.append(amt).append("|");
        sign.append(retCode).append("|");
        sign.append(retMsg).append("|");
        sign.append(payStatus).append("|");
        sign.append(notifyNum).append("|");
        sign.append(cardType);
        logger.error("bis refund 通知cashier签名明文: " + sign.toString());
        try {
            return RSAEncoderUtil.sign(sign.toString());
        } catch (Exception e) {
            logger.error("bis refund 通知cashier签名异常", e);
        }
        return "";
    }

    /**
     * 是否发起退款交易
     * 
     * @param oriOutOrderId
     * @return
     */
    private boolean isSendTkOrder(String oriOutOrderId) {
        boolean flag = true;
        // 根据原交易银行订单号获取退款订单
        List<BankOrder> tkBankOrders = bankOrderService.getBankOrdersByOriBankOrderId(oriOutOrderId);
        if (tkBankOrders != null && tkBankOrders.size() > 0) {
            // 同一支付订单下多笔退款时候, 前一笔退款状态为成功或者失败的情况下, 才允许做下一笔退款
            for (int i = 0; i < tkBankOrders.size(); i++) {
                String orderStatus = tkBankOrders.get(i).getOrderStatus();
                if (BankOrderStatus.PROCESS.equals(orderStatus)) {
                    // 已存在处理中退款交易
                    logger.error("BankInteractServiceImpl refund isSendTkOrder: 已存在处理中退款交易 "
                            + tkBankOrders.get(i).getOrderId());
                    flag = false;
                    break;
                }
            }
        }
        return flag;
    }

    /**
     * 是否发起退款交易
     * 
     * @param oriOutOrderId
     * @return
     */
   /* private boolean isSendTkOrder(String oriOutOrderId) {
        boolean flag = true;
        // 根据原交易银行订单号获取退款订单
        List<BankOrder> tkBankOrders = bankOrderService.getBankOrdersByOriBankOrderId(oriOutOrderId);
        if (tkBankOrders != null && tkBankOrders.size() > 0) {
            // 同一支付订单下多笔退款时候, 前一笔退款状态为成功或者失败的情况下, 才允许做下一笔退款
            for (int i = 0; i < tkBankOrders.size(); i++) {
                String orderStatus = tkBankOrders.get(i).getOrderStatus();
                if (BankOrderStatus.PROCESS.equals(orderStatus)) {
                    // 已存在处理中退款交易
                    logger.error("BankInteractServiceImpl refund isSendTkOrder: 已存在处理中退款交易 " + tkBankOrders.get(i).getOrderId());
                    flag = false;
                    break;
                }
            }
        }
        return flag;
    }*/
    
    /**
     * 自动路由请求对象
     * 
     * @return
     */
    private RouteMessage getRouteReq(BaseMessage message, ExPayBaseMessage expayMsg) {
        RouteMessage routeMessage = new RouteMessage();
        routeMessage.setCustId(message.getSpecial2());
        routeMessage.setGopayOrderId(expayMsg.getOrderId());
        routeMessage.setBankCode(expayMsg.getBank());
        routeMessage.setProdCode(expayMsg.getBankBusProd().value);
        // 自动路由交易金额获取接口传送的结算金额
        routeMessage.setTransAmt(new BigDecimal(expayMsg.getSettleAmt()));
        routeMessage.setSpecial(expayMsg.getSpecial());
        return routeMessage;
    }
 
    /**
     * 是否为自动路由
     * 
     * @param merId
     * @return
     */
    private boolean isRouteOrWhiteList(String merId) {
        // 是否为白名单商户
        boolean isWhite = bisBankWhiteListMerchantsService.isWhiteListMerchant(merId);
        if (AUTO_ROUTING.equals(bisConfig.get("GOPAY.AUTO.ROUTING")) || isWhite) {
            return true;
        } else {
            return false;
        }
    }

    public SmsSupportController getSmsController() {
        return smsController;
    }

    public void setSmsController(SmsSupportController smsController) {
        this.smsController = smsController;
    }



}